﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using SystemCenterSoa.ApiLibrary.PermissionsValidation;
using SystemCenterSoa.DtoModel.Common;
using SystemCenterSoa.DtoModel.SystemManager;
using SystemCenterSoa.Service.SystemManager;

namespace Net1905CoreDemo.ApiDemo.Lib
{
    public class UserTokenVerificationAttribute : Attribute, IActionFilter
    {
        private AdminUserService _adminUserService;
        private IHttpContextAccessor _iHttpContextAccessor;
        public UserTokenVerificationAttribute(AdminUserService adminUserService, IHttpContextAccessor iHttpContextAccessor)
        {
            _adminUserService = adminUserService;
            _iHttpContextAccessor = iHttpContextAccessor;
        }
        public void OnActionExecuted(ActionExecutedContext context)
        {
           
        }
        /// <summary>
        /// 实现过滤器接口的请求执行前的
        /// </summary>
        /// <param name="context"></param>
        public void OnActionExecuting(ActionExecutingContext context)
        {

            //从上下文中(context) 获取请求详情, 并转换为  Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor
            Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor cad = 
                ((Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor)context.ActionDescriptor);

            #region 首先先判断接口是否允许匿名访问,  如果是匿名访问接口, 必须在接口上加 AllowAnonymousAttribute 特性
            //从控制器(Controller)中获取是否有AllowAnonymousAttribute 特性, 如果有则不进行验证,直接跳过去
            AllowAnonymousAttribute[] authoritybtnAttribute = (AllowAnonymousAttribute[])
              cad.ControllerTypeInfo
              .GetCustomAttributes(typeof(AllowAnonymousAttribute), false);
            if (authoritybtnAttribute.Length > 0)
            {
                return;
            }
            //从请求(Action)中获取是否有AllowAnonymousAttribute 特性, 如果有则不进行验证,直接跳过去
            authoritybtnAttribute = (AllowAnonymousAttribute[])
               cad.MethodInfo.GetCustomAttributes(typeof(AllowAnonymousAttribute), false);
            if (authoritybtnAttribute.Length > 0)
            {
                return;
            }
            #endregion

            string token = AdminUserService.GetTokenInHeader();
            LoginUserDto loginUser =_adminUserService.GetLoginUserInRedisByToken(token);
            if (string.IsNullOrEmpty(token)
                || loginUser==null) //如果token为空 或者 验证不通过, 那说明没有登录
            {
                ResultModel<bool> model = new ResultModel<bool>();

                model.code = ResultCode.NoLogin;
                model.data = false;
                model.mess = "您没有登录!";
                context.Result = new ContentResult()  //短路,  当你需要从当前申请直接跳出,不往下执行是可以利用短路来实现
                {
                    Content = JsonConvert.SerializeObject(model)
                };
                return;
            }

            //获取请求(action)下面是否标注module_code
            string moduleCode = "";

            ApiModuleRelationAttribute[] amra = (ApiModuleRelationAttribute[])
              cad.MethodInfo.GetCustomAttributes(typeof(ApiModuleRelationAttribute), false);
            if (amra.Length > 0)
            {
                moduleCode = amra[0].ModuleCode;
            }

            //如果action下面没有获取module_code, 就从 controller获取
            if (string.IsNullOrWhiteSpace(moduleCode))
            {
                amra = (ApiModuleRelationAttribute[])
             cad.ControllerTypeInfo.GetCustomAttributes(typeof(ApiModuleRelationAttribute), false);
                if (amra.Length > 0)
                {
                    moduleCode= amra[0].ModuleCode;
                }
            }
            ///如果获取的模块code 不为空, 那说明这个接口需要验证
            if (!string.IsNullOrWhiteSpace(moduleCode))
            {
                //验证登录用户下面有没有这个模块的权限
                bool bl = loginUser.ModelCodes.Contains(moduleCode);

                if (!bl)
                {
                    ResultModel<bool> model = new ResultModel<bool>();

                    model.code = ResultCode.NoAuthorization;
                    model.data = false;
                    model.mess = "您没有权限!";
                    context.Result = new ContentResult()  //短路,  当你需要从当前申请直接跳出,不往下执行是可以利用短路来实现
                    {
                        Content = JsonConvert.SerializeObject(model)
                    };
                    return;
                }
            }


        }
    }
}
